package com.yswy.common.wxOrder.V3;

import cn.hutool.core.io.FileUtil;
import com.aliyun.oss.ServiceException;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Data
public class WxPayConfigV3 {
    private Integer id;
    // 商户号
    private String mchId;
    // 商户API证书序列号
    private String mchSerialNo;
    // 商户私钥文件
    private String privateKeyPath;
    // 商户私钥文件X509Certificate
    private String certificateKeyPath;
    // APIv3密钥
    private String key;
    // APPID
    private String appid;
    // 微信服务器地址
    private String domain;
    // 接收结果通知地址 支付
    private String notifyDomain;
    // 接收结果通知地址 退款
    private String notifyRefund;

    /**
     * 获取商户的私钥文件
     *
     * @param filename 证书地址
     * @return 私钥文件
     */
    public PrivateKey getPrivateKey(String filename) {
        try {
            return PemUtil.loadPrivateKey(new FileInputStream(filename));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new ServiceException("私钥文件不存在");
        }
    }

    /**
     * 获取签名验证器
     */
    public Verifier getVerifier() {
        // 获取商户私钥
        final PrivateKey privateKey = getPrivateKey(privateKeyPath);
        // 私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);
        // 身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        try {
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId, wechatPay2Credentials, key.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | GeneralSecurityException | HttpCodeException e) {
            e.printStackTrace();
        }

        try {
            return certificatesManager.getVerifier(mchId);
        } catch (NotFoundException e) {
            e.printStackTrace();
            throw new ServiceException("获取签名验证器失败");
        }
    }

    /**
     * 获取微信支付的远程请求对象
     *
     * @return Http请求对象
     */
    public CloseableHttpClient getWxPayClient() {

        // 获取签名验证器
//        Verifier verifier = getVerifier();

        // 获取商户私钥
        final PrivateKey privateKey = getPrivateKey(privateKeyPath);
        X509Certificate certificate = getCertificate(
                FileUtil.getInputStream(certificateKeyPath));
//        System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
//        System.out.println("版本号:" + certificate.getVersion());
//        System.out.println("签发者：" + certificate.getIssuerDN());
//        System.out.println("有效起始日期：" + certificate.getNotBefore());
//        System.out.println("有效终止日期：" + certificate.getNotAfter());
//        System.out.println("主体名：" + certificate.getSubjectDN());
//        System.out.println("签名算法：" + certificate.getSigAlgName());
//        System.out.println("签名：" + certificate.getSignature().toString());
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, privateKey)
                .withWechatPay(Arrays.asList(certificate));
//        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
//                .withMerchant(mchId, mchSerialNo, privateKey)
//                .withValidator(new WechatPay2Validator(verifier));

        return builder.build();
    }

    /**
     * 获取证书
     *
     * @param inputStream 证书文件
     * @return {@link X509Certificate} 获取证书
     */
    public static X509Certificate getCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
}

